package com.fast.alden.admin.security;

import com.fast.alden.admin.security.component.TokenAuthenticationFilter;
import com.fast.alden.security.config.WhiteListConfig;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
@Slf4j
public class SecurityConfig {
    @Resource
    private TokenAuthenticationFilter tokenAuthenticationFilter;
    @Resource
    private AccessDeniedHandler accessDeniedHandler;
    @Resource
    private AuthenticationEntryPoint authenticationEntryPoint;
    @Resource
    private WhiteListConfig whiteListConfig;
    @Resource
    private AuthorizationManager<RequestAuthorizationContext> authz;
    @Resource
    private UserDetailsService userDetailsService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        // 路由权限配置
        http.authorizeHttpRequests((authorizationManagerRequestMatcherRegistry) -> {
            // 白名单中的url无需鉴权
            whiteListConfig.getUrls().forEach(url -> {
                log.info(String.format("%s加入白名单", url));
                authorizationManagerRequestMatcherRegistry.requestMatchers(url).permitAll();
            });
            // 对于所有自定义webapi均使用动态鉴权（部分webapi可能在白名单中，跳过了动态鉴权步骤）
            authorizationManagerRequestMatcherRegistry.requestMatchers("/api/v1.0/admin/**").access(authz);
            // 其余请求登录即可
            authorizationManagerRequestMatcherRegistry.anyRequest().authenticated();
        });

        // 允许跨域
        http.cors(withDefaults());

        // 关闭csrf，防止通过伪造用户请求来访问受信用站点的非法请求访问
        http.csrf(AbstractHttpConfigurer::disable);

        // 使用无状态session
        http.sessionManagement(httpSecuritySessionManagementConfigurer -> {
            httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        });

        // 指定使用的UserDetailsService
        http.userDetailsService(userDetailsService);

        // 用户名密码校验前加入token校验
        http.addFilterBefore(tokenAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);

        // 禁用security默认的登录退出
        http.formLogin(AbstractHttpConfigurer::disable);
        http.logout(AbstractHttpConfigurer::disable);

        // 设置异常处理
        http.exceptionHandling(httpSecurityExceptionHandlingConfigurer -> {
            httpSecurityExceptionHandlingConfigurer.accessDeniedHandler(accessDeniedHandler);
            httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint(authenticationEntryPoint);
        });

        return http.build();
    }
}
